﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Globalization;
using SoftwareConsulting.Interfaces.BasicEntities;
using SoftwareConsulting.BI11.Studio.InternalServices;

namespace SoftwareConsulting.BI11.Studio.BasicEntities
{    
    /// <summary>
    /// Класс именованной иерархии
    /// </summary>
    [Serializable]
    public class NamedHierarchy<T>:Hierarchy<T>, INamedHierarchy<T> where T:INamed
    {        
        private string _name; //название

        /// <summary>
        /// Возвращает как строку (т.е. имя)
        /// </summary>
        /// <returns></returns>
        override public string ToString()
        {
            return _name;
        }

        /// <summary>
        /// Возвращает название
        /// </summary>        
        virtual public string Name
        {
            get
            {
                return _name;
            }            
        }

        /// <summary>
        /// Устанавливает название
        /// </summary>
        /// <param name="newName"></param>
        virtual public void SetName(string newName)
        {
            _name = newName;
        }

        /// <summary>
        /// Сортирует элементы иерархии в алфавитном порядке согласно текущей культуре и без учета регистра
        /// </summary>
        /// <remarks>пузырьком</remarks>
        public void Sort()
        {
            Sort(CultureInfo.CurrentCulture, CompareOptions.IgnoreCase);
        }

        /// <summary>
        /// Сортирует элементы иерархии в алфавитном порядке с учетом культуры и опций сравнения
        /// </summary>
        /// <remarks>пузырьком</remarks>
        public void Sort(CultureInfo culture, CompareOptions options)
        {                       
            int c = ItemsCount;
            for (int i = 0; i < c; i++)            
            {
                for (int j = c - 1; j > i; j--)                
                {
                    T cur = GetItemByPosition(j);
                    string curname = cur.Name;
                    if (string.Compare(GetItemByPosition(j - 1).Name, curname, culture, options) == 1)
                    {
                        UpItem(j);
                    }                                  
                    INamedHierarchy<T> h = cur as INamedHierarchy<T>;
                    if (h != null)
                    {
                        h.Sort(culture, options);
                    }
                }
            }
        }        

        /// <summary>
        /// Возвращает название элемента с учетом его глубины
        /// </summary>
        /// <remarks>добавляет пробелы перед названием</remarks>        
        public string NameWithDeep
        {
            get
            {
                return _name.PadLeft(Deep + _name.Length, ' ');             
            }
        }

        /// <summary>
        /// Возвращает полное название элемента (с учетом его родителей)
        /// </summary>
        /// <remarks>разделитель между родительским элементом и текущим - точка</remarks>
        public string FullName
        {
            get
            {
                if ((Parent == null) || !(Parent is INamedHierarchy<T>))
                    return Name;
                return (Parent as INamedHierarchy<T>).FullName + '.' + Name;
            }
        }

        /// <summary>
        /// Возвращает первый встреченный элемент по его имени (нерекурсивно)
        /// </summary>
        /// <param name="needName"></param>
        /// <returns></returns>
        public T GetFirstItemByName(string needName)
        {
            foreach (T item in this)
            {
                if (item.Name == needName)
                    return item;
            }
            return default(T);
        }

        /// <summary>
        /// Возвращает элементы с указанным именем
        /// </summary>                
        public INamedHierarchy<T> GetItemsByName(string needName, bool recursively)
        {
            INamedHierarchy<T> resItems = new NamedHierarchy<T>();
            foreach(T curItem in this)
            {            
                if (curItem.Name.Equals(needName))
                {
                    resItems.Add(curItem);
                }
                INamedHierarchy<T> childHierarchy = null;
                if (recursively && ((childHierarchy = curItem as INamedHierarchy<T>) != null))                
                {
                    INamedHierarchy<T> inner = childHierarchy.GetItemsByName(needName, true);
                    foreach(T innerItem in inner)                    
                    {
                        resItems.Add(innerItem);
                    }
                }
            }
            return resItems;
        }                               
        
        /// <summary>
        /// Конструктор класса
        /// </summary>
        /// <param name="owner"></param>
        public NamedHierarchy(INamedHierarchy<T> owner)
            : base(owner)
        {            
        }        

        /// <summary>
        /// Конструктор класса по умолчанию
        /// </summary>
        public NamedHierarchy():base()
        {            
        }
    }
}
